#ifndef __BLOCK_MANAGER_H__
#define __BLOCK_MANAGER_H__

#include "common/common_types.h"

struct BlockInfo {
    IncomingDataPacket* inputData;
    OutgoingDataPacket* outputData[SHIFTS_COUNT];
};

struct Cell;
class IFr;

class BlockManager {
public:
    BlockManager(uint32_t kCount, uint32_t jCount, uint32_t iCount, uint32_t speCount);

    void packData(Cell*** cells, float tau, IFr*** forces, int forcesCount);
    void addAccels(Cell*** cells);

    SpeInitData* getSpeInit(int speNum) const {
        assert(speNum < _speCount);
        return &_speInitDatas[speNum];
    }

    ~BlockManager();
private:
    bool _isValidShift(int k, int j, int i, int shiftIdx) {
        const IntCoords& shift = SHIFTS[shiftIdx];
        int newK = k + shift.k;
        int newJ = j + shift.j;
        int newI = i + shift.i;
        bool result = newK >= 0 && newK <= _kCount && newJ >= 0 && newJ <= _jCount && newI >= 0 && newI <= _iCount;
        //printf("      _isValidShift(%d, %d, %d): %s\n", newK, newJ, newI, result ? "true" : "false");
        return result;
    }
    IncomingDataPacket* _getInput(int k, int j, int i, int shiftIdx) {
        if (_isValidShift(k, j, i, shiftIdx)) {
            return SHIFT_IDX(_blocks, k, j, i, shiftIdx).inputData;
        } else {
            return _dummyInput;
        }
    }

    int _kCount;
    int _jCount;
    int _iCount;
    int _speCount;
    BlockInfo*** _blocks;
    SpeInitData* _speInitDatas;
    ForcesArray* _forces;
    IncomingDataPacket* _dummyInput;
};

#endif // __BLOCK_MANAGER_H__
